#include "StdAfx.h"
#include "Utils.h"
#include "Poom.h"

void Utils::EnableMenuItem(HWND hParentWnd, int MenuItemId, bool Enable)
{
    HWND hMenuBar = SHFindMenuBar(hParentWnd);

    CToolBarCtrl menu;
    menu.Attach(hMenuBar);

    TBBUTTONINFO tbi = {0};
    tbi.cbSize = sizeof(TBBUTTONINFO);
    tbi.dwMask = TBIF_STATE;
    menu.GetButtonInfo(MenuItemId, &tbi);

    if (Enable == true)
        tbi.fsState |= TBSTATE_ENABLED;
    else
        tbi.fsState &= ~TBSTATE_ENABLED;

    menu.SetButtonInfo(MenuItemId, &tbi);

    menu.Detach();
}

HRESULT Utils::GetPOutlookApp(CComPtr<IPOutlookApp2> &POutlookApp)
{
    CPoom *pPoom = CPoom::GetThis();
    if (pPoom == NULL)
        return E_POINTER;

    POutlookApp = pPoom->GetPOutlookApp();
    if (POutlookApp == NULL)
        return E_POINTER;

    return S_OK;
}

HRESULT
Utils::GetContactDetails(
    const CEOID ContactId,
    const CEPROPID PropId,
    CString *pName,
    CString *pNumber)
{
    CComPtr<IPOutlookApp2> POutlookApp;
    HRESULT hr = GetPOutlookApp(POutlookApp);
    if (FAILED(hr))
        return hr;

    CComPtr<IItem> Item;
    hr = POutlookApp->GetItemFromOidEx(ContactId, 0, &Item);
    if (FAILED(hr))
        return hr;

    HANDLE hHeap = GetProcessHeap();
    const CEPROPID PropIds[2] = { PIMPR_FILEAS, PropId };
    CEPROPVAL *pPropVal = NULL;
    ULONG BufferSize = 0;
    hr = Item->GetProps(
        PropIds,
        CEDB_ALLOWREALLOC,
        sizeof(PropIds) / sizeof(CEPROPID),
        &pPropVal,
        &BufferSize,
        hHeap);
    if (FAILED(hr))
        return hr;

    if (pName != NULL)
        *pName = pPropVal[0].val.lpwstr;

    if (pNumber != NULL)
        *pNumber = pPropVal[1].val.lpwstr;

    HeapFree(hHeap, 0, pPropVal);

    return S_OK;
}

DWORD SafePathRemoveFileSpec(TCHAR *Path, UINT PathLength)
{
    if (Path == NULL || PathLength == 0)
        return ERROR_INVALID_PARAMETER;

    size_t StringLength = 0;
    HRESULT hr = StringCchLength(Path, PathLength, &StringLength);
    if (FAILED(hr))
        return ERROR_INVALID_PARAMETER;

    size_t i;
    for (i = StringLength - 1; i > 0; --i)
    {
        if (Path[i] == _T('\\') || Path[i] == _T('/'))
            break;
    }

    Path[i] = '\0';

    return ERROR_SUCCESS;
}

DWORD
SafePathCombine(
    TCHAR *CombinedPath,
    UINT CombinedPathLength,
    const TCHAR *Path,
    const TCHAR *File)
{
    if (CombinedPath == NULL || CombinedPathLength == 0)
        return ERROR_INVALID_PARAMETER;

    ZeroMemory(CombinedPath, CombinedPathLength);
    HRESULT hr = StringCchCat(CombinedPath, CombinedPathLength, Path);
    if (FAILED(hr))
        return ERROR_INSUFFICIENT_BUFFER;

    size_t StringLength = 0;
    hr = StringCchLength(CombinedPath, CombinedPathLength, &StringLength);
    if (FAILED(hr))
        return ERROR_INVALID_PARAMETER;

    if (CombinedPath[StringLength - 1] != _T('\\') ||
        CombinedPath[StringLength - 1] != _T('/'))
    {
        hr = StringCchCat(CombinedPath, CombinedPathLength, _T("\\"));
        if (FAILED(hr))
            return ERROR_INSUFFICIENT_BUFFER;
    }

    hr = StringCchCat(CombinedPath, CombinedPathLength, File);
    if (FAILED(hr))
        return ERROR_INSUFFICIENT_BUFFER;

    return ERROR_SUCCESS;
}

DWORD
Utils::GetFileFromModulePath(
    HINSTANCE hInst,
    TCHAR *FileName,
    UINT FileNameLength,
    const TCHAR *File)
{
    if (FileName == NULL || FileNameLength == 0)
        return ERROR_INVALID_PARAMETER;

    TCHAR ModuleFile[MAX_PATH];
    DWORD Length = GetModuleFileName(hInst, ModuleFile, MAX_PATH);
    if (Length == 0)
        return ERROR_GEN_FAILURE;

    DWORD Err = SafePathRemoveFileSpec(ModuleFile, MAX_PATH);
    if (Err != ERROR_SUCCESS)
        return Err;

    Err = SafePathCombine(FileName, FileNameLength, ModuleFile, File);
    if (Err != ERROR_SUCCESS)
        return Err;

    return ERROR_SUCCESS;
}

HRESULT
Utils::ChooseContact(
    HWND hParentWnd,
    CString *pContactName,
    CString *pContactNumber,
    CEOID *pContactId,
    CEPROPID *pPropertyId)
{
    const CEPROPID c_propidAllEmail = PIMPR_ALL_COMMUNICATION_METHODS;
    CHOOSECONTACT cc = {0};

    // Setup the CHOOSECONTACT structure.
    cc.cbSize = sizeof(cc);
    cc.dwFlags = CCF_RETURNCONTACTNAME | CCF_RETURNPROPERTYVALUE;
    cc.rgpropidRequiredProperties = &c_propidAllEmail; 
    // Number of properties specified in the c_propidAllEmail array.
    cc.cRequiredProperties = 1;
    cc.hwndOwner = hParentWnd;

    // Display the Contact Chooser control and prompt the user to choose a contact.
    HRESULT hr = ChooseContact(&cc);
    if (FAILED(hr))
        goto CleanUp;

    if (pContactName)
        *pContactName = cc.bstrContactName;

    if (pContactNumber)
        *pContactNumber = cc.bstrPropertyValueSelected;

    if (pContactId)
        *pContactId = cc.oidContactID;

    if (pPropertyId)
        *pPropertyId = cc.propidSelected;

CleanUp:
    // Free memory.
    SysFreeString(cc.bstrContactName);
    SysFreeString(cc.bstrPropertyValueSelected);

    return hr;
}

int Utils::MessageBoxRes(HWND hWnd, UINT Caption, UINT Msg, UINT Type)
{
    CString CaptionText;
    CaptionText.LoadString(Caption);

    CString MsgText;
    MsgText.LoadString(Msg);

    return MessageBox(hWnd, MsgText, CaptionText, Type);
}
